﻿/**
/// ScrimpNet.Core Library
/// Copyright © 2005-2011
///
/// This module is Copyright © 2005-2011 Steve Powell
/// All rights reserved.
///
/// This library is free software; you can redistribute it and/or
/// modify it under the terms of the Microsoft Public License (Ms-PL)
/// 
/// This library is distributed in the hope that it will be
/// useful, but WITHOUT ANY WARRANTY; without even the implied
/// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
/// PURPOSE.  See theMicrosoft Public License (Ms-PL) License for more
/// details.
///
/// You should have received a copy of the Microsoft Public License (Ms-PL)
/// License along with this library; if not you may 
/// find it here: http://www.opensource.org/licenses/ms-pl.html
///
/// Steve Powell, spowell@scrimpnet.com
**/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using ScrimpNet.Text;

namespace ScrimpNet.Cryptography
{
    public partial class CryptoUtils
    {
        /// <summary>
        /// Perform crypto operations using value stored in machineKey of computer.  Uses same algoritm asp.net uses to Encode cookies and perform other cryptological functions
        /// </summary>
        public class Machine
        {
            /// <summary>
            /// Encodes text using machine key.  Note:  Multiple calls with same <paramref name="plainText"/> will result in different return strings but will decode correctly
            /// </summary>
            /// <param name="plainText">Unencrypted text to encrypt</param>
            /// <returns>Hex string of Encodeed <paramref name="plainText"/></returns>
            public static string Encode(string plainText)
            {
                byte[] bytes = UnicodeEncoding.Unicode.GetBytes(plainText);
                return Encode(bytes);
            }

            /// <summary>
            /// Encodes byte array using machine key. Note:  Multiple calls with same <paramref name="plainBytes"/> will result in different return strings but will decode correctly
            /// </summary>
            /// <param name="plainBytes">UnEncodeed bytes to Encode</param>
            /// <returns>Hex string of Encodeed <paramref name="plainBytes"/></returns>
            public static string Encode(byte[] plainBytes)
            {                
                return MachineKey.Encode(plainBytes, MachineKeyProtection.Encryption );
            }

            /// <summary>
            /// Encodes an object using machine key.  Uses binary serialization to convert <paramref name="objectToEncode"></param>.  Note:  Multiple calls with same <paramref name="objectToEncode"/> will result in different return strings but will decode correctly
            /// </summary>
            /// <param name="plainTextValue">UnEncodeed object to Encode</param>
            /// <returns>Hex string of Encodeed <paramref name="objectToEncode"/></returns>
            public static string Encode(object objectToEncode)
            {
                return Encode(Serialize.To.Binary(objectToEncode));
            }

            /// <summary>
            /// Decodes a hex based string that was generated by one of the Encode functions
            /// </summary>
            /// <param name="encodedString">Hex string generated using machine key</param>
            /// <returns>String representation of original value.  NOTE:  Applications might need to deserialize returned value into objects</returns>
            public static string Decode(string encodedString)
            {
                byte[] decodedBytes = MachineKey.Decode(encodedString, MachineKeyProtection.Encryption);
                return UnicodeEncoding.Unicode.GetString(decodedBytes);
            }

            /// <summary>
            /// Decode a hex based string that was generated by one of the Encode functions.  Use this version when <paramref name="encodedString"/> represents a non-string
            /// </summary>
            /// <typeparam name="T">Object type that should be hydrated from decoded bytes.  Must be a class type</typeparam>
            /// <param name="encodedString">Hex string generated using machine key</param>
            /// <returns>Hydrated object using binary serialization of decoded bytes</returns>
            public static T Decode<T>(string encodedString) where T:class
            {
                byte[] decodedBytes = MachineKey.Decode(encodedString, MachineKeyProtection.Encryption);
                return Serialize.From.Binary<T>(decodedBytes);
            }

            /// <summary>
            /// Create a hash of a specific range of text
            /// </summary>
            /// <param name="textToHash">Source bytes upon which hash will be calculated</param>
            /// <returns>Hex representation of hash of this value</returns>
            public static string Hash(string textToHash)
            {
                byte[] bytes = UnicodeEncoding.Unicode.GetBytes(textToHash);
                return Hash(bytes);
            }

            /// <summary>
            /// Create a hash of a specific range of text
            /// </summary>
            /// <param name="bytesToHash">Source bytes upon which hash will be calculated</param>
            /// <returns>Hex representation of hash of this value</returns>
            public static string Hash(byte[] bytesToHash)
            {
                return MachineKey.Encode(bytesToHash, MachineKeyProtection.Validation);
            }

            /// <summary>
            /// Create a hash of a specific range of text.  Uses binary serialization to convert <paramref name="objectToHash"></param>.
            /// </summary>
            /// <param name="objectToHash">Source bytes upon which hash will be calculated</param>
            /// <returns>Hex representation of hash of this value</returns>
            public static string Hash(object objectToHash)
            {
                byte[] objBytes = Serialize.To.Binary(objectToHash);
                return Hash(objBytes);
            }
        }
    }
}
